#ifndef __QpwDatabase__
#define __QpwDatabase__

#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QUuid>
#include <QtCore/QVariant>

namespace QpwXML {

class Values : public QMap<QString,QVariant> {
public:
    virtual ~Values() {}

    QUuid uuid() const { return QUuid( (*this)["uuid"].toString() ); }
    void setUuid( const QUuid & uuid ) { (*this)["uuid"] = uuid.toString(); }

};

class Row {
public:
    explicit Row( const QUuid & id ) : uuid(id) {}

    bool isValid() const { return !uuid.isNull(); }
    virtual Values values() const = 0;
    virtual void setValues( const Values & values ) = 0;

    inline bool operator == ( const Row & row ) { return this->uuid == row.uuid; }
    inline bool operator != ( const Row & row ) { return this->uuid != row.uuid; }

    QUuid uuid;

};

class Database {
public:
    explicit Database( const QString & filePath = QString() );
    virtual ~Database();

    QString filePath() const { return p_FilePath; }

    virtual bool load( const QString & filePath = QString() );
    virtual bool save( const QString & filePath = QString() );

protected:
    virtual void setData( QList<Values> data ) = 0;
    virtual QList<Values> data() const = 0;

private:
    QString p_FilePath;

};

template < typename RowBasedType >
class DatabaseTemplate : public Database {
public:
    explicit DatabaseTemplate( const QString & filePath = QString() ) : Database(filePath) {}
    virtual ~DatabaseTemplate() {}

    inline RowBasedType & add( const RowBasedType & row ) {

        if ( row.uuid.isNull() ) {

            RowBasedType newRow(row);
            newRow.uuid = QUuid::createUuid();
            rows[newRow.uuid] = newRow;

            return rows[newRow.uuid];
        } else {

            rows[row.uuid] = row;

        }

        return rows[row.uuid];
    }
    QMap<QUuid,RowBasedType> rows;

    RowBasedType baseValue;

protected:
    void setData( QList<Values> data ) {

        RowBasedType row;

        foreach ( Values values, data ) {

            row.uuid = values["uuid"].toString();
            row.setValues(values);
            rows[values.uuid()] = row;

        }

    }
    QList<Values> data() const {

        QList<Values> data;
        Values values;

        foreach ( RowBasedType row, rows.values() ) {

            values = row.values();
            values["uuid"] = row.uuid.toString();
            data.append(values);

        }

        return data;
    }

};

};

#endif//__QpwDatabase__
